#include <cstdio>

#include "GRDECLData.h"
#include "GeoGrid.h"
#include "mesh3d.h"

int main() {
    std::string input_path = "../../input/GridB";
    std::string output_path = "../../output/GridB";
    constexpr double mesh_scale = 20.0f; // 100.0 for GridA, 20.0 for GridB
    constexpr int samples = 256; // interpolation samples
    constexpr int strategy = 1; // meshing strategy
    
    constexpr double expand_top = -1050;
    constexpr double expand_bottom = -400;
    constexpr double expand_X_ratio = 0.1;
    constexpr double expand_Y_ratio = 0.1;

    GRDECLData baseGrid(input_path + "/baseGrid.out");
    baseGrid.SetOutputPath(output_path);
    baseGrid.ReadFaultFromFile(input_path + "/faults.txt");
    // baseGrid.WriteVTK(output_path + "/baseGrid.vtk", true);
    // baseGrid.WriteLayerVTK(output_path + "/baseGrid");

    GRDECLData fineGrid(input_path + "/fineGrid.out");
    fineGrid.SetOutputPath(output_path);
    fineGrid.ReadPropsFromFileOpt(input_path + "/Props.txt");
    // fineGrid.PrintHeadProps();
    // fineGrid.WriteVTK(output_path + "/fineGrid.vtk", true);

    // For different scale
    // std::vector<Point> fault_points;
    // std::vector<INDEX> fault_lines;
    // std::vector<INDEX> fault_quads;
    // baseGrid.GetFaultsFromFile(fault_points, fault_lines, fault_quads);

    GeoGrid baseGeoGrid(&baseGrid);
    baseGeoGrid.SetGridSize(mesh_scale);
    baseGeoGrid.setStrategy(strategy);
    baseGeoGrid.SetExpandInfo(expand_top, expand_bottom, expand_X_ratio, expand_Y_ratio);

    // Get the naive bottom surface
    std::vector<Point3d> pts;
    std::vector<INDEX> bdrs;
    std::vector<INDEX> tris; // store the indices of the points
    // baseGrid.GetNaiveBottomSurface(pts, bdrs, tris);
    baseGeoGrid.GetSurfaceBorderFault(pts, bdrs);

    baseGeoGrid.SetSurfaceByBottomSurface(pts, bdrs);
    baseGeoGrid.Expand();

    auto expand_info = baseGeoGrid.GetExpandInfo();

    Mesh3D mesh(baseGeoGrid);

    // mesh.InterpolateTetraMesh(fineGrid, samples); // basic version
    mesh.InterpolateExpandTetraMesh(fineGrid, expand_info, samples); // expand version

    if (mesh.WriteVTK(output_path + "/mesh3d_basic.vtk", false, true)) // expand, cellData
        printf("Success to generate mesh3d_basic.vtk!\n");
    if (mesh.WriteVTK(output_path + "/mesh3d_expand.vtk", true, true)) // expand, cellData
        printf("Success to generate mesh3d_expand.vtk!\n");

    return 0;
}
